#include "packetstream.h"

PacketClass::PacketClass(char _type, ENetPacketFlag _flag, enet_uint8 _chanel)
:	m_CurrentByte(0),
	m_CurrentBit(0),
	m_Channel(_chanel) 
{	
	m_Packet = enet_packet_create(NULL, 32, _flag);	
	WriteChar(_type);
};

PacketClass::PacketClass(ENetPacket *_packet)
:	m_CurrentByte(0),
	m_CurrentBit(0),
	m_Packet(_packet) 
{

}

void PacketClass::Shrink() 
{
	int Size = m_CurrentByte;
	if(m_CurrentBit & 7)
		Size++;
	enet_packet_resize(m_Packet, Size);
}

void PacketClass::AlignBitIndex() 
{	
	if(m_CurrentBit & 7) 
	{
		m_CurrentBit = 0;
		m_CurrentByte++;
	}
}

void PacketClass::AlignAndExpand(int _newSize) 
{
	AlignBitIndex();
	
	size_t NewPacketSize = m_CurrentByte + _newSize;
	if(NewPacketSize > m_Packet->dataLength)
		enet_packet_resize(m_Packet, NewPacketSize << 1);
}

void PacketClass::WriteBit(bool _data) 
{	
	if(m_CurrentBit == 0) 
	{
		AlignAndExpand(1);
		m_Packet->data[m_CurrentByte] = 0;
	}

	m_Packet->data[m_CurrentByte] |= _data << m_CurrentBit;

	m_CurrentBit++;
	if(m_CurrentBit == 8) 
	{
		m_CurrentBit = 0;
		m_CurrentByte++;
	}
}

void PacketClass::WriteChar(char _data) 
{
	AlignAndExpand(1);

	m_Packet->data[m_CurrentByte] = _data;
	m_CurrentByte++;
}

void PacketClass::WriteInt(int _data) 
{
	AlignAndExpand(sizeof(int));

	*((int *)&m_Packet->data[m_CurrentByte]) = _data;
	m_CurrentByte += sizeof(int);
}

void PacketClass::WriteFloat(float _data) 
{
	AlignAndExpand(sizeof(float));

	*((float *)&m_Packet->data[m_CurrentByte]) = _data;
	m_CurrentByte += sizeof(float);
}

void PacketClass::WriteString(const char *_data) 
{
	int StringLength = strlen(_data);
	AlignAndExpand(StringLength + 1);

	strcpy((char*)&m_Packet->data[m_CurrentByte], _data);
	m_CurrentByte += StringLength;

	m_Packet->data[m_CurrentByte] = 0;
	m_CurrentByte++;
}

bool PacketClass::ReadBit() 
{
	bool Bit = !!(m_Packet->data[m_CurrentByte]&(1<<m_CurrentBit));

	m_CurrentBit++;
	if(m_CurrentBit == 8) 
	{
		m_CurrentBit = 0;
		m_CurrentByte++;
	}

	return Bit;
}

char PacketClass::ReadChar() 
{
	AlignBitIndex();

	char Char = m_Packet->data[m_CurrentByte];
	m_CurrentByte++;

	return Char;
}

int PacketClass::ReadInt() 
{
	AlignBitIndex();

	int Int = *(int*)(&m_Packet->data[m_CurrentByte]);
	m_CurrentByte += sizeof(int);

	return Int;
}

float PacketClass::ReadFloat() 
{
	AlignBitIndex();

	float Float = *(float*)(&m_Packet->data[m_CurrentByte]);
	m_CurrentByte += sizeof(float);

	return Float;
}

const char *PacketClass::ReadString() 
{
	AlignBitIndex();

	const char *String = (const char *)(&m_Packet->data[m_CurrentByte]);
	m_CurrentByte += strlen(String) + 1;

	return String;
}
